#pragma once
#include <utility>
namespace tpl
{
template <typename R, typename... Args>
struct FunctorBase
{
  virtual R operator()(Args&&... args) = 0;

  virtual ~FunctorBase() {}
};

template <typename CalledObjecType, typename R, typename... Args>
struct Functor : public FunctorBase<R, Args...>
{
  Functor(CalledObjecType&& obj)
    : _obj(obj)
  {
  }
  R operator()(Args&&... args) { return _obj(std::forward<Args>(args)...); }

private:
  CalledObjecType _obj;
};

template <typename... Args>
struct Function;

template <typename R, typename... Args>
struct Function<R(Args...)>
{
  template <typename CalledObjectType>
  Function(CalledObjectType&& f)
  {
    this->_functor = new Functor<CalledObjectType, R, Args...>(std::forward<CalledObjectType>(f));
  }

  ~Function()
  {
    delete _functor;
    _functor = nullptr;
  }

  R operator()(Args&&... args) { return (*_functor)(std::forward<Args>(args)...); }

private:
  FunctorBase<R, Args...>* _functor;
};
}